package com.cr.business.service.impl;

import com.cr.business.domain.TbUserBaseInfo;
import com.cr.business.domain.TbUserEntityInfo;
import com.cr.business.domain.dto.UserReqDto;
import com.cr.business.domain.dto.app.RegDto;
import com.cr.business.domain.dto.app.UpdatePasswordDto;
import com.cr.business.domain.dto.app.UpdatePhoneDto;
import com.cr.business.domain.vo.UserDetailInfoVo;
import com.cr.business.mapper.TbUserBaseInfoMapper;
import com.cr.business.mapper.TbUserEntityInfoMapper;
import com.cr.business.service.ITbUserBaseInfoService;
import com.cr.business.service.TbRegionService;
import com.cr.common.constant.CacheConstants;
import com.cr.common.constant.Constants;
import com.cr.common.core.redis.RedisCache;
import com.cr.common.exception.ServiceException;
import com.cr.common.exception.user.CaptchaException;
import com.cr.common.exception.user.CaptchaExpireException;
import com.cr.common.utils.DateUtils;
import com.cr.common.utils.SecurityUtils;
import com.cr.common.utils.StringUtils;
import com.cr.common.utils.uuid.IdUtils;
import com.cr.common.utils.uuid.RandomUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 用户基本信息Service业务层处理
 *
 * @author tang
 * @date 2025-08-19
 */
@Service
public class TbUserBaseInfoServiceImpl implements ITbUserBaseInfoService
{
    @Resource
    private TbUserBaseInfoMapper tbUserBaseInfoMapper;

    @Resource
    private TbUserEntityInfoMapper tbUserEntityInfoMapper;

    @Resource
    private TbRegionService regionService;

    @Resource
    private RedisCache redisCache;

    /**
     * 查询用户基本信息列表
     *
     * @param dto 查询参数
     * @return 用户基本信息
     */
    @Override
    public List<TbUserBaseInfo> selectTbUserBaseInfoList(UserReqDto dto)
    {
        return tbUserBaseInfoMapper.selectTbUserBaseInfoList(dto);
    }

    /**
     * 批量删除用户基本信息
     *
     * @param userIds 需要删除的用户基本信息主键
     * @return 结果
     */
    @Override
    public int deleteTbUserBaseInfoByUserIds(String[] userIds)
    {
        return tbUserBaseInfoMapper.deleteTbUserBaseInfoByUserIds(userIds);
    }

    @Override
    public int updateStatus(TbUserBaseInfo info) {
        return tbUserBaseInfoMapper.updateTbUserBaseInfo(info);
    }

    @Override
    public UserDetailInfoVo getDetailInfo(String userId, String entityId) {
        UserDetailInfoVo vo = new UserDetailInfoVo();
        // 查询基本信息
        TbUserBaseInfo tbUserBaseInfo = tbUserBaseInfoMapper.selectTbUserBaseInfoByUserId(userId);
        if(tbUserBaseInfo != null) {

            tbUserBaseInfo.setPassword(null);
            vo.setBaseInfo(tbUserBaseInfo);

            // 认证状态（0-未认证，1-已认证，2-审核中，3-审核失败）
            String authStatus = tbUserBaseInfo.getAuthStatus();
            if(!"0".equals(authStatus)) {
                // 查询主体信息
                TbUserEntityInfo tbUserEntityInfo;
                if(StringUtils.isNotBlank(entityId)) {
                    tbUserEntityInfo = tbUserEntityInfoMapper.selectTbUserEntityInfoById(entityId);
                } else {
                    tbUserEntityInfo = tbUserEntityInfoMapper.selectTbUserEntityInfoByUserId(userId);
                }
                if(tbUserEntityInfo != null) {
                    tbUserEntityInfo.setProvince(regionService.getRegionNameByCode(tbUserEntityInfo.getProvince()));
                    tbUserEntityInfo.setCity(regionService.getRegionNameByCode(tbUserEntityInfo.getCity()));
                    tbUserEntityInfo.setDistrict(regionService.getRegionNameByCode(tbUserEntityInfo.getDistrict()));
                    tbUserEntityInfo.setTown(regionService.getRegionNameByCode(tbUserEntityInfo.getTown()));
                    tbUserEntityInfo.setVillage(regionService.getRegionNameByCode(tbUserEntityInfo.getVillage()));
                }
                vo.setEntityInfo(tbUserEntityInfo);
            }
        }
        return vo;
    }

    @Override
    public int register(RegDto regDto) {
        // 判断密码是否一致
        if(! regDto.getPassword().equals(regDto.getComfirmPassword())) {
            throw new ServiceException("密码不一致！");
        }
        // 校验验证码
        validateCode(regDto.getCode(), regDto.getUuid());
        // 判断手机号是否已注册
        String phone = regDto.getPhone();
        if(validatePhoneRegistered(phone)) {
            throw new ServiceException("该手机号已注册！");
        }

        TbUserBaseInfo tbUserBaseInfo = new TbUserBaseInfo();
        tbUserBaseInfo.setUserId(IdUtils.simpleUUID());
        tbUserBaseInfo.setPhone(phone);
        tbUserBaseInfo.setPassword(SecurityUtils.encryptPassword(regDto.getPassword()));
        tbUserBaseInfo.setNickName(regDto.getNickName());
        // 判断昵称是否填写
        if(StringUtils.isBlank(regDto.getNickName())) {
            tbUserBaseInfo.setNickName("用户_" + phone);
        }
        tbUserBaseInfo.setRegTime(DateUtils.getNowDate());

        // 插入用户信息
        return tbUserBaseInfoMapper.insertTbUserBaseInfo(tbUserBaseInfo);
    }

    @Override
    public int forgetPassword(RegDto regDto) {
        // 判断密码是否一致
        if(! regDto.getPassword().equals(regDto.getComfirmPassword())) {
            throw new ServiceException("密码不一致！");
        }
        // 校验验证码
        validateCode(regDto.getCode(), regDto.getUuid());
        // 判断手机号是否已注册
        String phone = regDto.getPhone();
        if(! validatePhoneRegistered(phone)) {
            throw new ServiceException("该手机号尚未注册！");
        }

        // 修改用户密码
        TbUserBaseInfo tbUserBaseInfo = new TbUserBaseInfo();
        tbUserBaseInfo.setPhone(phone);
        tbUserBaseInfo.setPassword(SecurityUtils.encryptPassword(regDto.getPassword()));
        return tbUserBaseInfoMapper.updateUserPasswordByPhone(tbUserBaseInfo);
    }

    /**
     * 校验验证码
     * @param code 验证码
     * @param uuid 唯一表示符号
     */
    private void validateCode(String code, String uuid) {
        String verifyKey = CacheConstants.SMS_CODE_KEY + StringUtils.nvl(uuid, "");
        String captcha = redisCache.getCacheObject(verifyKey);
        if (captcha == null) {
            throw new CaptchaExpireException();
        }

        redisCache.deleteObject(verifyKey);
        if (! code.equalsIgnoreCase(captcha)) {
            throw new CaptchaException();
        }
    }

    /**
     * 校验手机号是否已注册
     * @param phone 手机号
     */
    private boolean validatePhoneRegistered(String phone) {
        TbUserBaseInfo tbUserBaseInfo = tbUserBaseInfoMapper.selectUserByPhone(phone);
        return tbUserBaseInfo != null;
    }

    @Override
    public boolean updateAvatar(String userId, String avatar) {
        return tbUserBaseInfoMapper.updateUserAvatar(userId, avatar) > 0;
    }

    @Override
    public int updateNickName(String userId, String nickName) {
        return tbUserBaseInfoMapper.updateUserNickName(userId, nickName);
    }

    @Override
    public int updatePassword(UpdatePasswordDto param) {

        if(! param.getPassword().equals(param.getComfirmPassword())) {
            // 密码不一致
            throw new ServiceException("新密码不一致！");
        }

        // 查询用户信息
        TbUserBaseInfo tbUserBaseInfo = tbUserBaseInfoMapper.selectTbUserBaseInfoByUserId(param.getUserId());
        if(! SecurityUtils.matchesPassword(param.getOldPassword(), tbUserBaseInfo.getPassword())) {
            throw new ServiceException("旧密码错误！");
        }

        tbUserBaseInfo.setPassword(SecurityUtils.encryptPassword(param.getPassword()));
        return tbUserBaseInfoMapper.updateTbUserBaseInfo(tbUserBaseInfo);
    }

    @Override
    public int updatePhone(UpdatePhoneDto param) {
        // 校验验证码
        validateCode(param.getCode(), param.getUuid());
        // 判断手机号是否已注册
        String phone = param.getPhone();
        if(validatePhoneRegistered(phone)) {
            throw new ServiceException("该手机号已注册！");
        }

        // 修改用户密码
        TbUserBaseInfo tbUserBaseInfo = new TbUserBaseInfo();
        tbUserBaseInfo.setUserId(param.getUserId());
        tbUserBaseInfo.setPhone(phone);
        return tbUserBaseInfoMapper.updateTbUserBaseInfo(tbUserBaseInfo);
    }

    @Override
    public Map<String, Object> generateTempPassword(String userId) {
        TbUserBaseInfo user = tbUserBaseInfoMapper.selectTbUserBaseInfoByUserId(userId);
        if(user == null) {
            throw new ServiceException("用户不存在！");
        }
        // 生成临时密码
        String tempPwd = String.valueOf(RandomUtil.getRandomNumber(10000000, 99999999));
        // 失效时间
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MINUTE, Constants.TEMP_PASSWORD_EXPIRATION);
        Date expiration = cal.getTime();

        // 缓存临时密码
        String verifyKey = CacheConstants.APP_USER_TEMP_PWD_KEY + user.getPhone();
        redisCache.setCacheObject(verifyKey, SecurityUtils.encryptPassword(tempPwd), Constants.TEMP_PASSWORD_EXPIRATION, TimeUnit.MINUTES);

        // 返回数据
        Map<String, Object> result = new HashMap<>();
        result.put("tempPwd", tempPwd);
        result.put("expiration", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, expiration));
        return result;
    }

    @Override
    public TbUserBaseInfo getUserInfo(String userId) {
        return tbUserBaseInfoMapper.selectTbUserBaseInfoByUserId(userId);
    }
}
